package com.hk.core.elasticsearch.repository;

import co.elastic.clients.elasticsearch._types.SuggestMode;
import co.elastic.clients.elasticsearch.core.search.FieldSuggester;
import co.elastic.clients.elasticsearch.core.search.FieldSuggesterBuilders;
import co.elastic.clients.elasticsearch.core.search.SuggestSort;
import com.hk.commons.query.Order;
import com.hk.commons.query.QueryModel;
import com.hk.commons.query.page.QueryPage;
import com.hk.core.elasticsearch.query.Condition;
import org.springframework.data.domain.Persistable;
import org.springframework.data.elasticsearch.repository.ReactiveElasticsearchRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * @author Kevin
 */
public interface BaseReactiveElasticsearchRepository<T extends Persistable<ID>, ID extends Serializable>
        extends ReactiveElasticsearchRepository<T, ID> {

    /**
     * 分页查询
     *
     * @param queryModel queryModel
     * @return {@link QueryPage}
     */
    Mono<QueryPage<T>> queryForPage(QueryModel<T> queryModel);

    /**
     * 分页查询
     *
     * @param conditions 查询条件
     * @param pageIndex  分页参数
     * @param pageSize   分页参数
     * @param orders     排序字段
     * @return {@link QueryPage}
     */
    Mono<QueryPage<T>> queryForPage(List<Condition> conditions, int pageIndex, int pageSize, Order... orders);

    /**
     * 条件查询不分页
     */
    Flux<T> findAll(List<Condition> conditions, Order... orders);

    /**
     * 根据不为空的字段更新
     *
     * @param t t
     */
    default Mono<Void> bulkUpdate(T t) {
        return bulkUpdate(Collections.singletonList(t));
    }

    /**
     * 批量更新多少不为空的属性值
     *
     * @param entities entities
     */
    Mono<Void> bulkUpdate(Collection<T> entities);

    /**
     * completion Suggest 建议词查询
     *
     * @param fieldName fieldName
     * @param prefix    prefix
     */
    default Flux<String> completionSuggest(String fieldName) {
        var suggester = FieldSuggesterBuilders.completion()
                .field(fieldName)
                .size(20)
                .skipDuplicates(true)
                .build()._toFieldSuggester();
        return suggest(suggester);
    }

    /**
     * phrase Suggest 建议词查询
     *
     * @param fieldName  fieldName
     * @param confidence confidence
     * @param maxErrors  maxErrors
     * @param value      value
     */
    default Flux<String> phraseSuggest(String fieldName,
                                       Double confidence,
                                       Double maxErrors,
                                       String value) {
        var suggester = FieldSuggesterBuilders.phrase()
                .field(fieldName)
                .confidence(confidence)
                .maxErrors(maxErrors)
                .text(value)
                .size(20)
                .build()._toFieldSuggester();
        return suggest(suggester);
    }

    /**
     * term Suggest 建议词查询
     *
     * @param fieldName   fieldName
     * @param maxTermFreq maxTermFreq
     * @param suggestMode suggestMode
     * @param value       value
     */
    default Flux<String> termSuggest(String fieldName,
                                     float maxTermFreq,
                                     SuggestMode suggestMode,
                                     String value) {
        var suggester = FieldSuggesterBuilders.term()
                .field(fieldName)
                .sort(SuggestSort.Score)
                .maxTermFreq(maxTermFreq)
                .suggestMode(suggestMode)
                .size(20)
                .text(value)
                .size(QueryModel.DEFAULT_PAGE_SIZE)
                .build()._toFieldSuggester();
        return suggest(suggester);
    }

    /**
     * 建议词查询
     */
    Flux<String> suggest(FieldSuggester suggester);

    /**
     * 根据条件查询记录数
     *
     * @param t t
     * @return count
     */
    Mono<Long> count(T t);

}
